package com.finance.cooperate.data.base;

import com.finance.cooperate.common.utils.SpringContextUtil;
import com.finance.cooperate.dao.local.scope.CooperateRequestScope;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * @ClassName AbstractProcess
 * @Description 添加初始化方法
 * @Author shen
 * @Date 2023/8/10 18:08
 * @Modify ...
 */
@Slf4j
public abstract class AbstractProcess implements Process{


    /**
     * 手数据初始化
     * @param builder
     * @return
     */
    protected Map<String, String> init(String userId, Builder<Reader> builder) {

        // 存放特征
        Map<String, String> map = new HashMap<>();

        ApplicationContext context = SpringContextUtil.getApplicationContext();
        CooperateRequestScope cooperateRequestScope = (CooperateRequestScope) context.getBean("cooperateRequestScope");

        if (userId == null){
            log.error("用户id为空");
            return null;
        }

        List<Reader> readers = builder.build();

        ExecutorService threadPool = ReaderThreadPool.getInstance().getThreadPool();

        try {

//            long beginTimeX = System.currentTimeMillis();

            //设置子线程共享

            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

            // 创建存储任务的容器
            List<Callable<Map<String, String>>> tasks = new ArrayList<>();

            for (Reader reader : readers) {

                Callable<Map<String, String>> task = () -> {

                    RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);

                    Map<String, String> m = new HashMap<>();
                    try {

//                        long beginTime = System.currentTimeMillis();
                        m = reader.read(userId);
//                        long endTime = System.currentTimeMillis();

//                        if ((endTime - beginTime) > 3000) {
//                               System.out.println("Reader: " + reader.getClass() + "; 执行时间：" + (endTime - beginTime));
//                        }


                    } catch (Exception e) {

                        if (e instanceof DataAccessResourceFailureException) {
                            // 数据库连接异常，重尝试

                            for (int i = 0; i < 3; i ++) {

                                log.error("DB error, trying... "+ i +"  uid:" + userId + "；loanNum：" + cooperateRequestScope.getLoanNum() + "；read：" + reader.getClass());

                                try {
                                    m = reader.read(userId);

                                    break;
                                } catch (Exception e1) {

                                    if (i == 2) {
                                        log.error("uid：" + userId + "；loanNum：" + cooperateRequestScope.getLoanNum() + "；read：" + reader.getClass(), e1);
                                    }

                                }


                            }


                        } else {
                            log.error("uid：" + userId + "；loanNum：" + cooperateRequestScope.getLoanNum() + "；read：" + reader.getClass(), e);
                        }

                    }
                    return m;
                };

                // 将task添加进任务队列
                tasks.add(task);

            }

            // 获取任务的返回结果
            List<Future<Map<String, String>>> results = threadPool.invokeAll(tasks);

            // 输出结果
            for (Future<Map<String, String>> future: results) {

                map.putAll(future.get());

            }

//            long endTimeX = System.currentTimeMillis();

//            System.out.println("Reader 执行总时间: " + (endTimeX - beginTimeX));

        } catch (Exception e) {

            log.error("uid：" + userId + "；loanNum：" + cooperateRequestScope.getLoanNum(), e);
        }

        return map;
    }

}
